<?php

use Fox\Config as Config;
use Fox\DefResponse as DefResponse;
use Fox\Response as Response;


/**
 * 获取boot实例
 */
function boot(){
	return Fox\Boot::getInstance();
}

/**
 * 增加filter
 */
function filter($call){
	$boot = boot();
	$boot->route->addFilter($call);
}


/**
 * 重定向到指定的url或者闭包函数
 * @param   $url 匹配的url
 * @param  $to  重定向到指定的url，或者闭包函数
 */
function route($url, $handler = null) {
	$fox = boot();
	$config = $fox->config;

	if (!isset($config['route'])) {
		$config['route'] = [];
	}

	$route = $config['route'];
	if ($handler === null) {
		$route = array_merge($route, $url);
	} else {
		$route[$url] = $handler;
	}

	$fox->config['route'] = $route;
	$fox->route->resetRoutes($route);
}

/**
 * 显示一个视图文件 $view 可以是路径，不需要.php后缀
 * @param $view
 * @return Response
 */
function view($view) {
	$fox = boot();
	$viewPathBase = $fox->viewPath;
	if ($fox->config['tpl']) {
		return new DefResponse(['Content-Type: text/html'], combine_paths($viewPathBase, $view), DefResponse::BODY_TYPE_TPL);
	} else {
		return new DefResponse(['Content-Type: text/html'], combine_paths($viewPathBase, $view), DefResponse::BODY_TYPE_PHP);
	}
}

/**
 * 通过输出js脚本弹出提示，并跳转到指定url
 * @param $message
 * @param string $url
 */
function alert($message, $url = '#') {
	return html("<head><meta charset='UTF-8'/><script>alert('$message');location.href='$url';</script></head>");
}

/**
 *输出js脚本，http头：application/javascript
 * @param $js
 */
function js($js) {
	return response($js, 'application/javascript');
}

/**
 * 什么都不输出
 */
function none() {
	return new DefResponse([], '');
}

/**
 * 输出一段纯文本 http头：text/plain
 * @param $text
 */
function text($text) {
	return response($text, "text/plain");
}

/**
 * 输出json http头：application/json
 * @param $data
 */
function json($data) {
	return response(json_encode($data), 'application/json');
}

/**
 * 输出html http头：text/html
 * @param $html
 */
function html($html) {
	return response($html, 'text/html');
}

/**
 * 输出404
 * @return Response
 */
function e404() {
	return new Response(['HTTP/1.1 404 Not Found',
		'status: 404 Not Found'],
		'HTTP 404 Not Found');
}

/**
 * 重定向到指定url
 * @param $url
 * @param int $code 状态码，默认302
 */
function redirect($url, $code = 302) {
	$state = 'HTTP/1.1 302 Found';
	if ($code == 301) {
		$state = 'HTTP/1.1 301 Moved Permanently';
	}
	$heads = [$state, 'Cache-Control:no-cache', "location:$url"];
	$body = '';
	return new DefResponse($heads, $body);
}

/**
 * 输出指定数据和http头
 * @param $data
 * @param $content_type
 */
function response($data, $content_type) {
	return new DefResponse(["Content-Type: $content_type"], $data);
}

/**
 * 下载文件到浏览器
 * @param $path 文件路径可以是url
 */
function down($path) {
	$heads = [];
	$name = basename($path);
	$heads[] = "Content-Description: File Transfer";
	$heads[] = 'Content-type: application/octet-stream';
	if (preg_match('/MSIE/', $_SERVER['HTTP_USER_AGENT'])) {
		//for IE
		$heads[] = 'Content-Disposition: attachment; filename="' . rawurlencode($name) . '"';
	} else {
		$heads[] = 'Content-Disposition: attachment; filename="' . $name . '"';
	}
	return new DefResponse($heads, $path, Response::BODY_TYPE_FILE);
}

/**
 * 重写到指定的url
 * @param $url
 */
function rewrite($url) {
	return new DefResponse(["Content-Type: $content_type"], $url, DefResponse::BODY_TYPE_REWRITE);
}

/**
 * 设置一个数据到视图数据，通过G()函数获取
 * @param $key
 * @param $val
 */
function S($key, $val) {
	Fox\ViewData::set($key, $val);
}

/**
 * 从视图数据中， 获取数据
 * @param $key
 * @return mixed
 */
function G($key) {
	return Fox\ViewData::get($key);
}

/**
 * 读取配置文件
 * @param $path 如 conf('lang.site.name'), 获取lang配置文件中site配置项，中name的值
 * @return $val
 */
function conf($path, $type = "PHP") {
	static $configFiles = [];
	$segs = explode('.', $path);
	$file = combine_paths(boot()->confPath, $segs[0] . ($type == 'PHP' ? ".php" : '.json'));
	$cf = null;
	if (isset($configFiles[$file])) {
		$cf = $configFiles[$file];
	} else {
		$cf = new Config($file, $type);
		$configFiles[$file] = $cf;
	}
	$ps = array_slice($segs, 1);
	return $cf->get(empty($ps) ? null : join($ps, '.'));
}

/**
 * 将客户端post过来的数据通过json_decode转换并返回
 * @param $assoc
 * @return object
 */
function J($assoc = true) {
	static $json;
	return $json ?: $json = json_decode(file_get_contents('php://input'), $assoc);
}

/**
 * 获取get，post，put，file 参数中的内容
 * @param $exp 表达式
 * @param null $def 默认值
 * @return array|null
 */
function P($exp, $def = null) {

	if (strpos($exp, ':') !== false) {
		list($type, $path) = explode(':', $exp);
	} else {
		$type = '';
		$path = $exp;
	}

	$parts = explode('.', $path);
	$first = strtoupper($parts[0]);

	if (isset($GLOBALS['_' . $first])) {
		$parts[0] = $first;
	} else {
		array_unshift($parts, $_SERVER['REQUEST_METHOD']);
	}

	$val = $GLOBALS['_' . $parts[0]];
	array_shift($parts);

	foreach ($parts as $key) {
		if (isset($val[$key])) {
			$val = $val[$key];
		} else {
			return $def;
		}
	}

	return is_array($val) ? $val : ($type != '' ? (I($type, $val) ? $val : $def) : $val);
}

function ns() {
	$namespace = join('\\', func_get_args());
	return preg_replace('/\\\+|\/+/', '\\', $namespace);
}

/**
 * 快捷函数，判断val是否是指定的类型
 * @param $type
 * @param $val
 * @return bool
 */
function I($type, $val) {
	return Fox\Validate::is($type, $val);
}

/**
 * 检测$data数组中每一个元素 是否符合$rules 中的规则。
 * @param $data 待检测数组
 * @param $rules 检测规则
 * @return array 检测失败的错误信息
 */
function C($data, $rules) {
	$errors = [];
	foreach ($rules as $key => $msg) {
		list($type, $name) = explode(':', $key);
		if (!Fox\Validate::is($type, $data[$name])) {
			$errors[$name] = $msg;
		}
	}
	return $errors;
}

/**
 * 获取DB的快捷函数
 * @param bool|false $tableName 当前操作的tableName
 * @param $db |def 当前操作的db
 * @return DataBase
 */
function D($tableName = '', $db = 'def') {
	$config = boot()->config;
	$d = new Fox\DataBase(isset($config['db']['dsn']) ? $config['db'] : $config['db'][$db]);
	return $d->table($tableName);
}

/**
 * 合并路径
 * @param $paths
 * @return $path
 */
function combine_paths() {
	$paths = join(DIRECTORY_SEPARATOR, func_get_args());
	return preg_replace('/\\\+|\/+/', DIRECTORY_SEPARATOR, $paths);
}

/**
 * 加载指定路径的文件。
 * @param $path 不需要.php后缀
 * @param null $construct_args
 * @return mixed|object
 */
function L($path) {
	static $loads = [];
	if (!isset($loads[$path])) {
		if (is_file($path . '.php')) {
			return $loads[$path] = include $path . '.php';
		}
		throw new Exception("加载 $path 失败,文件未找到！");
	} else {
		return $loads[$path];
	}
}

